package com.bite.job.Handler;


import Constants.RedisConstant;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bite.job.Constanst.JobConstants;
import com.bite.job.Mapper.ExamMapper;
import com.bite.job.Mapper.MessageTextMapper;
import com.bite.job.Mapper.UserSubmitMapper;
import com.bite.job.domain.Exam;
import com.bite.job.domain.Message;
import com.bite.job.domain.MessageText;
import com.bite.job.domain.UserExamInfo;
import com.bite.job.service.MessageService;
import com.bite.job.service.MessageTextService;
import com.bite.job.service.ServiceImpl.MessageServiceImpl;
import com.bite.job.service.ServiceImpl.MessageTextServiceImpl;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Component
@Slf4j
public class ExamHandler {

    @Autowired
    private StringRedisTemplate redis;

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private UserSubmitMapper userSubmitMapper;

    @Autowired
    private MessageTextServiceImpl messageTextService;

    @Autowired
    private MessageServiceImpl messageService;

    @XxlJob("examListHandler")
    public void examListHandler() {
        log.info("------------开始刷新redis--------------");

        //从数据库中查询竞赛信息
        //1.0首先更新未结束的竞赛信息
        refreshRedis(0);
        //2.0更新已经结束的竞赛信息
        refreshRedis(1);
    }

    //刷新redis
    private void refreshRedis(int type){

        List<Exam> examList = new ArrayList<>();
        //从数据库中查询数据
        //1.0查询未结束的竞赛
        if (type == 0){
            examList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                    .eq(Exam::getStatus, 1)
                    .gt(Exam::getEndTime, LocalDateTime.now())
                    .orderByDesc(Exam::getCreateTime));
        }else if (type == 1){
            examList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                    .eq(Exam::getStatus, 1)
                    .le(Exam::getEndTime, LocalDateTime.now())
                    .orderByDesc(Exam::getCreateTime));
        }

        if (CollUtil.isEmpty(examList)){
            return;
        }

        String keyList = "";
        if (type == 0){
            keyList = RedisConstant.UNFINISHED_EXAM_LIST;
        }else if (type == 1){
            keyList = RedisConstant.HISTORY_EXAM_LIST;
        }
        if (StrUtil.isEmpty(keyList)){
            log.info("刷新redis过程中，获取到keyList为空");
            return;
        }

        //在刷新id列表之前，需要先将之前的数据删除
        redis.delete(keyList);

        //获取到数据之后，将数据刷新到redis中
        List<String> listId = examList.stream().map(e -> e.getExamId().toString()).toList();
        redis.opsForList().rightPushAll(keyList, listId);
        Map<String, String> map =
                examList.stream().collect(Collectors.toMap(e -> RedisConstant.EXAM_DETAIL_KEY + e.getExamId(), JSONUtil::toJsonStr));
        redis.opsForValue().multiSet(map);
    }


    @XxlJob("examResultHandler")
    public void examResultHandler() {

        //当前时间
        LocalDateTime nowDate = LocalDateTime.now();
        //往前一天
        LocalDateTime minusDate = nowDate.minusDays(1);
        //查询符合条件的竞赛信息
        List<Exam> examList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                .select(Exam::getExamId, Exam::getTitle)
                .eq(Exam::getStatus, 1)
                .ge(Exam::getEndTime, minusDate)
                .le(Exam::getEndTime, nowDate));
        //如果在这段时间内没有结束的竞赛，则直接返回
        if (CollUtil.isEmpty(examList)){
            return;
        }
        Set<Long> examIdSet = examList.stream().map(Exam::getExamId).collect(Collectors.toSet());
        //接着统计竞赛用户信息
        List<UserExamInfo> userExamInfoList = userSubmitMapper.statsUserExamInfo(examIdSet);
        if (CollUtil.isEmpty(userExamInfoList)){
            throw new RuntimeException("没有查询到竞赛用户信息,请尽快联系管理员");
        }

        Map<Long, List<UserExamInfo>> map = userExamInfoList.stream().collect(Collectors.groupingBy(UserExamInfo::getExamId));
        List<MessageText> messageTextList = new ArrayList<>();
        List<Message> messageList = new ArrayList<>();
        for (Exam exam : examList) {
            List<UserExamInfo> userExamInfos = map.get(exam.getExamId());
            int totalUser = userExamInfos.size();
            int examRank = 1;
            for (UserExamInfo userExamInfo : userExamInfos) {
                MessageText messageText = new MessageText();
                String msgTitle =  exam.getTitle() + "——排名情况";
                String msgContent = "您所参与的竞赛：" + exam.getTitle()
                        + "，本次参与竞赛一共" + totalUser + "人， 您排名第"  + examRank++ + "名！" + "本次竞赛总分：" + userExamInfo.getScore();
                //设置消息内容
                messageText.setMessageTitle(msgTitle);
                messageText.setMessageContent(msgContent);
                messageText.setCreateBy(JobConstants.SENDER_ID);
                messageText.setUpdateBy(JobConstants.SENDER_ID);
                messageText.setCreateTime(LocalDateTime.now());
                messageText.setUpdateTime(LocalDateTime.now());
                messageTextList.add(messageText);

                //设置消息
                Message message = new Message();
                message.setSendId(JobConstants.SENDER_ID);
                message.setRecId(userExamInfo.getUserId());
                message.setCreateBy(JobConstants.SENDER_ID);
                message.setUpdateBy(JobConstants.SENDER_ID);
                message.setCreateTime(LocalDateTime.now());
                message.setUpdateTime(LocalDateTime.now());
                messageList.add(message);
            }
        }
        //保存消息内容到数据库中
        messageTextService.saveBatch(messageTextList);
        for (int i = 0; i < messageTextList.size(); i++) {
            messageList.get(i).setTextId(messageTextList.get(i).getTextId());
        }
        //保存消息到数据库中
        messageService.saveBatch(messageList);

    }























}
